package com.university.report.user.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.university.report.common.constant.RabbitMQConst;
import com.university.report.common.utils.ExcelUtils;
import com.university.report.common.utils.TimeUtils;
import com.university.report.model.entity.ReportInfo;
import com.university.report.model.entity.UserInfo;
import com.university.report.model.exception.UserNotFoundException;
import com.university.report.model.vo.ReportInfoVO;
import com.university.report.user.mapper.ReportInfoMapper;
import com.university.report.user.mapper.UserInfoMapper;
import com.university.report.user.service.ReportInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Jinondo
 * @since 2021-06-09
 */
@Service
@Slf4j
public class ReportInfoServiceImpl extends ServiceImpl<ReportInfoMapper, ReportInfo> implements ReportInfoService {

    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    ReportInfoMapper reportInfoMapper;

    @Autowired
    UserInfoMapper userInfoMapper;

    public static final int PAGE_MAX = 10;

    public static final BigDecimal temperature = new BigDecimal("37.5");


    @Override
    public Map<String, Object> getInfoByCond(Integer currentPage,String department, String dateString, Integer healthCon, Integer impRegion) {
        String from = null;
        String to = null;
        if (StringUtils.isNotEmpty(dateString)){
            List<String> onedays = TimeUtils.getOnedays(dateString);
            from = onedays.get(0);
            to = onedays.get(1);
        }

        IPage<ReportInfoVO> iPage = reportInfoMapper.selectByCond(new Page<>(currentPage,PAGE_MAX),department,healthCon,impRegion,from,to);
        List<ReportInfoVO> records = iPage.getRecords();
        long totalPage = iPage.getPages();
        long total=iPage.getTotal();
        Map<String, Object> map = new HashMap<String, Object>(3){{
            put("totalPage",totalPage);
            put("currentPage",currentPage);
            put("total",total);
            if (!records.isEmpty()){
                put("infos",records);
            }
        }};
        return map;
    }

    @Override
    public void exportData(HttpServletResponse response,
                           String department, String dateString) {
        try {
            List<ReportInfoVO> infoVOList;
            if (StringUtils.isEmpty(dateString)){
                infoVOList = reportInfoMapper.selectByDepNDateFull(department,null,null);
                ExcelUtils.exportExcel(response,infoVOList,ReportInfoVO.class,"健康上报表","健康上报信息");
                return;
            }
            List<String> onedays = TimeUtils.getOnedays(dateString);
            infoVOList = reportInfoMapper.selectByDepNDateFull(department,onedays.get(0),onedays.get(1));
            ExcelUtils.exportExcel(response,infoVOList,ReportInfoVO.class,"健康上报表","健康上报信息");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void exportDataByCond(HttpServletResponse response,Integer currentPage, String department, String dateString, Integer healthCon, Integer impRegion) {
        try {
            Map<String, Object> map = this.getInfoByCond(currentPage, department, dateString, healthCon, impRegion);
            if (map!=null && map.get("infos")!=null){
                ExcelUtils.exportExcel(response,(List<ReportInfoVO>) map.get("infos"),ReportInfoVO.class,"健康上报表","健康上报信息");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<ReportInfoVO> getInfoByDepNDate(String department, String timeString) {
        List<ReportInfoVO> infoVOList;
        if (StringUtils.isEmpty(timeString)){
            infoVOList = reportInfoMapper.selectByDepNDateFull(department,null, null);
            return infoVOList;
        }
        List<String> onedays = TimeUtils.getOnedays(timeString);
        infoVOList = reportInfoMapper.selectByDepNDateFull(department, onedays.get(0), onedays.get(1));
        return infoVOList;
    }

    @Override
    public List<ReportInfo> getInfoByTime(String timeString) {
        QueryWrapper<ReportInfo> wrapper = new QueryWrapper<>();
        Timestamp timestamp = Timestamp.valueOf(timeString+" 00:00:00");
        String format = DateFormatUtils.format(timestamp, "yyyy-MM-dd HH:mm:ss");
        wrapper.apply("UNIX_TIMESTAMP(report_date) >= UNIX_TIMESTAMP('" + format + "')");
        return baseMapper.selectList(wrapper);
    }

    @Override
    public Map<String, Object> getInfoToday(Integer currentPage) {
        List<String> todays = TimeUtils.getTodays();
        IPage<ReportInfoVO> iPage = reportInfoMapper.selectBetweenDate(new Page<>(currentPage,PAGE_MAX), todays.get(0), todays.get(1));
        List<ReportInfoVO> records = iPage.getRecords();
        long totalPage = iPage.getPages();
        long total=iPage.getTotal();
        Map<String, Object> map = new HashMap<String, Object>(){{
            put("totalPage",totalPage);
            put("currentPage",currentPage);
            put("userInfos",records);
        }};
        return map;
    }

    @Override
    public Map<String, Object> getInfoByDate(Integer currentPage, String timeString) {
        List<String> onedays = TimeUtils.getOnedays(timeString);
        IPage<ReportInfoVO> iPage = reportInfoMapper.selectBetweenDate(new Page<>(currentPage,PAGE_MAX), onedays.get(0), onedays.get(1));
        List<ReportInfoVO> records = iPage.getRecords();
        long totalPage = iPage.getPages();
        Map<String, Object> map = new HashMap<String, Object>(){{
            put("totalPage",totalPage);
            put("currentPage",currentPage);
            put("userInfos",records);
        }};
        return map;
    }

    @Override
    public List<ReportInfoVO> getReportInfoByUserIdSort(Integer userId) {
        List<ReportInfoVO> infoVOList = reportInfoMapper.selectByUserIdSort(userId);
        return infoVOList;
    }

    @Override
    public ReportInfoVO getOneInfoByUserId(Integer userId) {
        ReportInfoVO infoVO = reportInfoMapper.selectOneByUserId(userId);
        return infoVO;
    }

    /**
     * 这里需要使用事务
     * @param reportInfo
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ReportStatus report(ReportInfo reportInfo) {
        if(reportInfo==null){
            return ReportStatus.FAIL;
        }
        Integer userId = reportInfo.getUserId();
        UserInfo userInfo = userInfoMapper.selectById(userId);
        if (userInfo ==null) {
            throw new UserNotFoundException("用户id为 "+userId+" 的用户不存在！");
        }
        if (userInfo.getReportStatus()==1){
            return ReportStatus.REPORTED;
        }
        reportInfo.setReportDate(new Timestamp(System.currentTimeMillis()));
        int callback = baseMapper.insert(reportInfo);
        if (callback==1){
            userInfo.setReportStatus(1);
            userInfo.setUpdateTime(null);
            userInfoMapper.updateById(userInfo);
            return ReportStatus.SUCCESS;
        }
        return ReportStatus.FAIL;
    }

    @Override
    public void reportMQ(ReportInfo reportInfo) {
        try {
            Message msg= MessageBuilder.withBody(objectMapper.writeValueAsBytes(reportInfo)).setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT)
                    .build();
            // 发送消息
            rabbitTemplate.convertAndSend(RabbitMQConst.DIRECT_EXCHANGE,RabbitMQConst.REPORT_KEY,msg);
            log.info(">> 健康上报消息发送成功 <<");
        } catch (JsonProcessingException e) {
            log.info(">> 健康上报消息发送失败 <<");
            e.printStackTrace();
        }

    }

    @Override
    public List<ReportInfoVO> getUnusualHealthDate(String timeString) {
        List<String> onedays = TimeUtils.getOnedays(timeString);
        List<ReportInfoVO> infoVOList = reportInfoMapper.selectByTempNHealth(temperature, "异常%",onedays.get(0),onedays.get(1));
        return infoVOList;
    }

    @Override
    public List<ReportInfoVO> getUnusualHealthToday() {
        List<String> todays = TimeUtils.getTodays();
        List<ReportInfoVO> infoVOList = reportInfoMapper.selectByTempNHealth(temperature, "异常%",todays.get(0),todays.get(1));
        return infoVOList;
    }

    @Override
    public List<ReportInfoVO> getImpRegion(String timeString) {
        if (StringUtils.isEmpty(timeString)){
            return reportInfoMapper.selectByImpRegionEQ1(null,null);
        }
        List<String> onedays = TimeUtils.getOnedays(timeString);
        return reportInfoMapper.selectByImpRegionEQ1(onedays.get(0),onedays.get(1));
    }
}
